(in-package :experiment)

(defclass login (gwee:column-layout)
  ((prompt :initarg :prompt :accessor login-prompt))
  (:default-initargs
    :prompt "Subject Number:"
    :x :center :y :center
    :width 250
    :height 200
    :background (gwee:color 240 240 240)
    :border-color (gwee:color 170 170 170)
    :margin 10
    :padding 5))

(defclass option ()
  ((name :initarg :name :accessor option-name)
   (value :accessor option-value)
   (initial-value :initarg :initial-value :accessor option-initial-value)
   (values :initarg :values :accessor option-values)))

(defmethod shared-initialize :after ((obj option) slots &key)
  (setf (option-value obj) (option-initial-value obj)))
   
(defgeneric get-subject-from-user (login sessions options option-formatter))

(defmethod get-subject-from-user ((login login) sessions options option-formatter)
  "Returns 2 values, the subject ID and the session or :resume to resume a subject."
  (labels ((shipit (input type)
             (lambda (b)
               (declare (ignore b))
               (when (plusp (length (gwee:view-data input)))
                 (throw 'done (values (gwee:view-data input) type))))))
    (let* ((font (gwee:open-font "sans.ttf" 14))
           (text (make-instance 'gwee:text-area
                                :background (gwee:gray 240)
                                :border-color nil
                                :width :maximum
                                :data (login-prompt login)
                                :font font))
           (input (make-instance 'gwee:text-area
                                 :border-color (gwee:gray 0)
                                 :data ""
                                 :font font
                                 :left-padding 5
                                 :height 25
                                 :width 240
                                 :vertical-justification :center))
           (resume (make-instance 'gwee:button
                                  :width :maximum
                                  :font font
                                  :data "Resume"
                                  :disabled-p t
                                  :click-callback (shipit input :resume))))
      (setf (gwee:view-subviews login) `(,text
                                         ,input
                                         ,@(loop for i in sessions
                                              collect (make-instance 'gwee:button
                                                                     :width :maximum
                                                                     :font font
                                                                     :data (string-capitalize (first i))
                                                                     :click-callback (shipit input (first i))))
                                         ,@(when options (list (make-instance 'gwee:view :width :maximum :height 10)))
                                         ,@(loop for i in options
                                                collect (make-instance 'gwee:button
                                                                       :width :maximum
                                                                       :font font
                                                                       :data (option-value i)
                                                                       :format-function option-formatter
                                                                       :click-callback (let ((o i))
                                                                                         (lambda (b)
                                                                                           (setf (option-value o) (or (cadr (member (gwee:view-data b) (option-values o)))
                                                                                                                      (first (option-values o)))
                                                                                                 (gwee:view-data b) (option-value o)
                                                                                                 (gwee:view-needs-update-p b) t)))))
                                         ,(make-instance 'gwee:view :width :maximum :height 10)
                                         ,resume)
            (gwee:best-height login) :minimum
            (gwee:view-parent login) gwee:*top-view*)
      (gwee:sync-views)
      (gwee:draw-view login)
      (sdl:update-display)
      (unwind-protect
           (catch 'done
             (gwee:with-keyboard login
               (gwee:add-hook (gwee:key-press-hook login)
                              (lambda (view key)
                                (declare (ignore view))
                                (let ((ch (gwee:key-to-character key)))
                                  (when (characterp ch)
                                    (case ch
                                      (#\Backspace
                                       (when (plusp (length (gwee:view-data input)))
                                         (setf (gwee:view-data input) (subseq (gwee:view-data input) 0 (1- (length (gwee:view-data input))))
                                               (gwee:view-needs-update-p input) t)))
                                      (t
                                       (when (alphanumericp ch)
                                         (setf (gwee:view-data input) (concatenate 'string (gwee:view-data input) (string ch))
                                               (gwee:view-needs-update-p input) t))))
                                    (setf (gwee:disabled-p resume) (not (probe-file (get-suspend-file (gwee:view-data input))))
                                          (gwee:view-needs-update-p resume) t)))))
               (gwee:handle-gui-events)))
        (gwee:delete-view login)))))
